// Author: wsfuyibing <682805@qq.com>
// Date: 2025-06-24

package order

import (
	"context"
	"gitee.com/go-libs/db-xorm/db"
	"server/app/http/models"
	"server/app/kind"
	"server/app/lib/order/operations"
	"server/app/lib/order/operations/close"
	"server/app/lib/order/operations/create_goods"
	"server/app/lib/order/operations/create_session"
	"server/app/lib/order/operations/prepay_goods"
	"server/app/lib/order/operations/prepay_session"
	"sync"
)

var (
	once      = new(sync.Once)
	singleton Manager
)

type (
	// Manager
	// 订单管理器.
	Manager interface {
		// Close
		// 关闭订单.
		Close(ctx context.Context, sess *db.Session, order *models.Order, by kind.ClosedBy) (err error)

		// CreateOnGoods
		// 创建购物订单.
		CreateOnGoods(ctx context.Context, sess *db.Session, entity *operations.GoodsEntity, pre *operations.Prepay) (order *models.Order, err error)

		// CreateOnSession
		// 创建购票订单.
		CreateOnSession(ctx context.Context, sess *db.Session, entity *operations.SessionEntity, pre *operations.Prepay) (order *models.Order, err error)

		// NewGoodsEntity
		// 购物订单实体.
		NewGoodsEntity() *operations.GoodsEntity

		// NewSessionEntity
		// 购票订单实体.
		NewSessionEntity() *operations.SessionEntity

		// PrepayOnGoods
		// 基于商品试算.
		PrepayOnGoods(ctx context.Context, sess *db.Session, entity *operations.GoodsEntity) (pre *operations.Prepay, err error)

		// PrepayOnSession
		// 基于场次试算.
		PrepayOnSession(ctx context.Context, sess *db.Session, entity *operations.SessionEntity) (pre *operations.Prepay, err error)
	}

	manager struct{}
)

// New
// 管理器实例.
func New() Manager { return singleton }

func (o *manager) Close(ctx context.Context, sess *db.Session, order *models.Order, by kind.ClosedBy) (err error) {
	return close.New().Run(ctx, sess, order, by)
}

func (o *manager) CreateOnGoods(ctx context.Context, sess *db.Session, entity *operations.GoodsEntity, prepay *operations.Prepay) (order *models.Order, err error) {
	return create_goods.New().Run(ctx, sess, entity, prepay)
}

func (o *manager) CreateOnSession(ctx context.Context, sess *db.Session, entity *operations.SessionEntity, prepay *operations.Prepay) (order *models.Order, err error) {
	return create_session.New().Run(ctx, sess, entity, prepay)
}

func (o *manager) NewGoodsEntity() *operations.GoodsEntity {
	v := &operations.GoodsEntity{}
	v.Kind = kind.OrderKindGoods
	v.Goods = make(map[kind.GoodsId]*models.Goods)
	v.Items = make([]*models.OrderItem, 0)
	return v
}

func (o *manager) NewSessionEntity() *operations.SessionEntity {
	v := &operations.SessionEntity{}
	v.Kind = kind.OrderKindSession
	v.Goods = make(map[kind.GoodsId]*models.Goods)
	v.Items = make([]*models.OrderItem, 0)
	return v
}

func (o *manager) PrepayOnGoods(ctx context.Context, sess *db.Session, entity *operations.GoodsEntity) (pre *operations.Prepay, err error) {
	return prepay_goods.New().Run(ctx, sess, entity)
}

func (o *manager) PrepayOnSession(ctx context.Context, sess *db.Session, entity *operations.SessionEntity) (pre *operations.Prepay, err error) {
	return prepay_session.New().Run(ctx, sess, entity)
}

// +---------------------------------------------------------------------------+
// | Initialize singleton instance                                             |
// +---------------------------------------------------------------------------+

func init() {
	once.Do(func() {
		singleton = &manager{}
	})
}
